﻿#include "CardGame.h"
#include <ctime>


CardGame::CardGame()
{
	selfCards_node = Node::create();
}
static CardGame *s_SharedGame = nullptr;
CardGame *CardGame::getInstance()
{
	if (!s_SharedGame)
	{
		s_SharedGame = new (std::nothrow)CardGame;
	}
	return s_SharedGame;
}
void CardGame::cleanInstance()
{
	CC_SAFE_DELETE(s_SharedGame);
}

//将0-53的值，转变为对应的某张牌的精灵
Sprite *CardGame::getCardSpriteWithValue(int value)
{
	string file_name = "";

	if (value == 52) {
		// 小王
		file_name = "xiaowang.png";
	}
	else if (value == 53) {
		// 大王
		file_name = "dawang.png";
	}
	else {
		// 如何得到花色？
		int flower = value / 13 + 1;
		// 牌的值？
		int _value = value % 13 + 1;
		switch (flower) {
		case 1: // ♠️
			file_name = StringUtils::format("hei-%d.png", _value);
			break;
		case 2: // ♦️
			file_name = StringUtils::format("fk-%d.png", _value);
			break;
		case 3: // ♣️
			file_name = StringUtils::format("mh-%d.png", _value);
			break;
		case 4: // ♥️
			file_name = StringUtils::format("hong-%d.png", _value);
			break;
		default:
			break;
		}
	}

	Sprite *cardSprite = Sprite::createWithSpriteFrameName(file_name);
	cardSprite->setTag(value);//有助于从父节点通过tag值找到对应的牌的精灵
	return cardSprite;
}

void CardGame::shuffle(int a[], int len) {
	int index, temple, i;
	for (i = 0; i < 54; i++) {
		a[i] = i;
	}
	srand((unsigned)time(NULL));
	for (i = len - 1; i > 0; i--) {
		index = rand() % i;
		// 交换i索引和index索引里储存的值
		temple = a[i];
		a[i] = a[index];
		a[index] = temple;
	}
	// 打印下洗好牌后的情况
	for (i = 0; i < len; i++) {
		CCLOG("%d ", a[i]);
	}
}

//判断是否为王炸
bool isKingBomb(vector<int> arr)
{
	if (arr[0] >= 52 && arr[1] >= 52)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//判断是否为红十炸弹
bool isRedTenBomb(vector<int> arr)
{
	if ((arr[0] == 22 && arr[1] == 48) || (arr[0] == 48 && arr[1] == 22))
	{
		return true;
	}
	else
	{
		return false;
	}
}
//判断是否有王
//bool: is  has did 
bool hasKing(vector<int> arr)
{
	for (int i = 0; i <= arr.size(); i++)
	{
		if (arr[i] >= 52)
		{
			return true;
		}
		return false;
	}
}

//是否为对子
bool isDouble(vector<int> arr)
{
	if (hasKing(arr))
	{
		return false;
	}
	else if(arr[0] % 13 == arr[1] % 13)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//判断是否为三张或四张的炸弹
bool isBomb(vector<int> arr)
{
	//排除王的干扰
	if (hasKing(arr))
	{
		return false;
	}
	bool allSame = true;//假设初始点数都相同
	for (int i = 1; i < arr.size(); i++)
	{
		if (arr[0] % 13 != arr[i] % 13)
		{
			allSame = false;//遇到点数不相同 break结果
			break;
		}
	}
	if (allSame)
	{
		return true;
	}
	else
	{
		return false;
	}
}
//判断是否为顺子
bool isStraight(vector<int> arr)
{
	if (hasKing(arr))
	{
		return false;
	}
	vector<int> vec(14, 0);//vec来记录每个点数出现的次数
	for (int i = 0; i < arr.size(); i++)
	{
		vec[arr[i] % 13] += 1;
	}
	//判断既有K 又有A
	if (vec[12] > 0 && vec[0] > 0)
	{
		vec[0]--;
		vec[13]++;
	}
	//计算vec里连续出现的1的次数，只要出现1后，没出现1就中断
	int count = 0;
	for (int i = 0; i < vec.size(); i++)
	{
		if (vec[i] == 1)
		{
			count++;
		}
		else if(count!=0)
		{
			//连续的1发生中断
			break;
		}
	}
	if (count == arr.size())
	{
		return true;
	}
	else {
		return false;
	}
}

PokerType CardGame::getPokerTepyWithCards(vector<int>arr)
{
	// 获取所选牌的数量
	int len = (int)arr.size();

	if (len == 1) {
		return PokerType::POKER_TYPE_SINGLE;
	}
	else if (len == 2) {
		if (isKingBomb(arr)) {
			return PokerType::POKER_TYPE_KING_BOMB;
		}
		else if (isRedTenBomb(arr)) {
			return PokerType::POKER_TYPE_REDTEN_BOMB;
		}
		else if (isDouble(arr)) {
			return PokerType::POKER_TYPE_DOUBLE;
		}
	}
	else if (len == 3 || len == 4) {
		if (isBomb(arr)) {
			if (len == 3) {
				return PokerType::POKER_TYPE_THREE_BOMB;
			}
			else {
				return PokerType::POKER_TYPE_FOUR_BOMB;
			}
		}
		else if (isStraight(arr)) {
			return PokerType::POKER_TYPE_STRAIGHT;
		}
	}
	else if (len > 4) {
		if (isStraight(arr)) {
			return PokerType::POKER_TYPE_STRAIGHT;
		}
	}

	return PokerType::POKER_TYPE_ERROR;
}
void CardGame::closeSelfCards(int cards[], int count,float &cardOriginY)
{
	Size visibleSize = Director::getInstance()->getVisibleSize();
	//计算牌组放置的整体X轴居中位置
	int mid = count / 2;
	float midx = (visibleSize.width + 180) / 2;

	// 显示自己的牌
	// 显示
	for (int i = 0; i < count; i++) {

		// 区分当前这张牌的精灵是否存在
		Node *node = selfCards_node->getChildByTag(cards[i]);
		if (node) {
			// 如果该精灵已经存在，只需调整位置
			node->setPosition(Vec2(midx + 60 * (i - mid) + (count % 2 == 0 ? 30 : 0), node->getBoundingBox().size.height / 2 + 30));
		}
		else {
			Sprite *cardSprite = getCardSpriteWithValue(cards[i]);
			cardSprite->setScale(0.9);
			cardSprite->setPosition(Vec2(midx + 60 * (i - mid) + (count % 2 == 0 ? 30 : 0), cardSprite->getBoundingBox().size.height / 2 + 30));
			cardOriginY = cardSprite->getPositionY();
			selfCards_node->addChild(cardSprite);
		}
	}
}
//获取牌面值
int getValue(int tag)
{
	int res = tag % 13 + 1;
	// A
	if (res == 1) res = 14;
	// 2
	if (res == 2) res = 15;
	// 小王
	if (tag == 52) res = 16;
	// 大王
	if (tag == 53) res = 17;
	// 两张红十
	if (tag == 22 || tag == 48) res = 18;
	
	return res;
}
//获取手牌内能压的炸弹
vector<int> getBomb(int selfCards[], int selfCardsCount, vector<int> lastCards,PokerType type)
{
	vector<int> rebomb;
	vector<int> table(15,0);

	for (int i = 0; i < selfCardsCount; i++)
	{
		if (selfCards[i] == 52 || selfCards[i] == 53)
		{
			table[13]++;
		}
		else if (selfCards[i] == 22 || selfCards[i] == 48)
		{
			table[7]++;
			table[14]++;
		}
		else
		{
			table[getValue(selfCards[i]) - 3]++;
		}
	}
	//寻找最小的三张炸弹
	for (int i = 0; i <=12; i++)
	{
		if (table[i] == 3)
		{
			//把这个点数添加到结果中
			for (int j = selfCardsCount-1; j >= 0; j--)
			{
				if (type != POKER_TYPE_THREE_BOMB)
				{
					if (getValue(selfCards[j]) == i + 3)
					{
						rebomb.push_back(selfCards[j]);
						if (rebomb.size() == 3)
						{
							break;
						}
					}
				}
				else
				{
					if (getValue(selfCards[j]) == i + 3&& getValue(selfCards[j])>getValue(lastCards[0]))
					{
						rebomb.push_back(selfCards[j]);
						if (rebomb.size() == 3)
						{
							break;
						}
					}
				}
			
			}
			break;
		}
	}
	if (rebomb.size() != 3 && rebomb.size() > 0)
	{
		for (int i = 1; i >= 0; i--)
		{
			if (selfCards[i] == 22 || selfCards[i] == 48)
			{
				rebomb.push_back(selfCards[i]);
				if (rebomb.size() == 3)
				{
					break;
				}
			}
		}
	}

	//寻找最小的四张炸弹
	for (int i = 0; i <= 12; i++)
	{
		if (table[i] == 4)
		{
			//把这个点数添加到结果中
			for (int j = 0; j < selfCardsCount; j++)
			{
				if (getValue(selfCards[j]) == i + 3)
				{
					rebomb.push_back(selfCards[j]);
				}
			}
			break;
		}
	}
	if (rebomb.size() != 4 && rebomb.size() > 0)
	{
		for (int i = 1; i >= 0; i--)
		{
			if (selfCards[i] == 22 || selfCards[i] == 48)
			{
				rebomb.push_back(selfCards[i]);
				if (rebomb.size() == 4)
				{
					break;
				}
			}
		}
	}

	if (rebomb.size() == 0)
	{
		for (int i = 0; i < selfCardsCount; i++)
		{
			if (table[13] == 2)
			{
				if (selfCards[i] == 52 || selfCards[i] == 53)
				{
					rebomb.push_back(selfCards[i]);
				}
			}
			else if(table[14]==2)
			{
				if (selfCards[i] == 22 || selfCards[i] == 48)
				{
					rebomb.push_back(selfCards[i]);
				}
			}
		}
	}

	return rebomb;
}

vector<int>CardGame::suggest(int selfCards[],int selfCardsCount, vector<int> lastCards)
{
	vector<int> vec;
	//获取上家出牌的类型
	PokerType lastType = getPokerTepyWithCards(lastCards);
	//单牌
	if (lastType == POKER_TYPE_SINGLE)
	{
		//判断是否有更大的单牌
		for (int i = selfCardsCount - 1; i >= 0; i--) {
			//            selfCards[i] 和 lastCards[0] 进行比较
			if (getValue(selfCards[i]) > getValue(lastCards[0])) {
				vec.push_back(selfCards[i]);
				break;
			}
		}
		if (vec.size()==0)
		{
			vec = getBomb(selfCards, selfCardsCount, lastCards,POKER_TYPE_SINGLE);

		}
	}
	else if(lastType==POKER_TYPE_DOUBLE)
	{
		for (int i = selfCardsCount - 1; i > 0; i--)
		{
			int right = getValue(selfCards[i]);
			int left = getValue(selfCards[i - 1]);
			//判断只有一张黑十
			if (right == 10 && left != 10)
			{
				if (right > getValue(lastCards[0]))
				{
					//寻找一张红十来配对
					for (int j = selfCardsCount - 1; j >= 0; j--)
					{
						if (selfCards[j] == 22 || selfCards[j] == 48)
						{
							vec.push_back(selfCards[i]);
							vec.push_back(selfCards[j]);
							return vec;
						}
					}
				}
			}
			else if (right > getValue(lastCards[0]) && right == left&&right!=18)
			{
				vec.push_back(selfCards[i]);
				vec.push_back(selfCards[i - 1]);
				return vec;
			}
		}
		if (vec.size() == 0)
		{
			vec = getBomb(selfCards, selfCardsCount, lastCards,POKER_TYPE_DOUBLE);

		}
	}
	else if (lastType == POKER_TYPE_STRAIGHT)
	{
		vector<int> tem;
		int i = selfCardsCount - 1;
	a:
		log("ia=%d", i);
			for ( i ; i >=0 ; i--)
			{
				if (selfCards[i] % 13 + 1 > lastCards[0] % 13 + 1)
				{
					tem.push_back(selfCards[i]);
					if (tem.size() == lastCards.size())
					{
						if (isStraight(tem))
						{
							return tem;
						}
						else
						{
							log("i=%d", i);
							tem.clear();
							i=i+lastCards.size()-2;
							log("bi=%d", i);
							goto a;
						}
					}

					
				}
			}
			if (vec.size() == 0)
			{
				vec = getBomb(selfCards, selfCardsCount, lastCards,POKER_TYPE_STRAIGHT);

			}
		
	}
	else if(lastType == POKER_TYPE_THREE_BOMB)
	{
		vec = getBomb(selfCards, selfCardsCount, lastCards,POKER_TYPE_THREE_BOMB);
	}
	for (int i = 0; i < vec.size(); i++)
	{
		log("a=%d", vec[i]);
	}
	
	return vec;

}